﻿Imports System.IO

Public Class SaveFile
    ' Classes permettant la lecture/écriture binaire dans un fichier
    Private WriteFile As BinaryWriter = Nothing
    Private ReadFile As BinaryReader = Nothing

    ' Constantes d'identification des sections du fichier
    Const STATIONS_SECTION As Short = &HAA
    Const JUNCTIONS_SECTION As Short = &HBB
    Const TRAINS_SECTION As Short = &HCC
    Const RAILPOINTS_SECTION As Short = &HDD

    ' Constructeur en mode écriture
    Public Sub Create(FileName As String)
        WriteFile = New BinaryWriter(File.Open(FileName, FileMode.Create))
    End Sub

    ' Constructeur en mode lecture
    Public Sub Open(FileName As String)
        ReadFile = New BinaryReader(File.Open(FileName, FileMode.Open))
    End Sub

    ' SECTION STATIONS = &HAA
    '   INT IncStations
    '   INT RecordCount
    '   ARRAY(STATION) 
    '   <
    '       INT key
    '       INT X
    '       INT Y
    '       STRING Name
    '   >
    ' END SECTION

    ' Ecriture des stations de la simulation
    Public Sub WriteStations(Stations As Dictionary(Of Integer, Station), IncStations As Integer)
        ' Identifiant de la section
        WriteFile.Write(STATIONS_SECTION)
        ' Variable d'incrémentation de la simulation
        WriteFile.Write(IncStations)
        ' Nombre effectif de stations à écrire
        WriteFile.Write(Stations.Count)

        ' Pour chaque station
        For Each kvp As KeyValuePair(Of Integer, Station) In Stations
            WriteFile.Write(kvp.Key)
            WriteFile.Write(kvp.Value.X)
            WriteFile.Write(kvp.Value.Y)
            WriteFile.Write(kvp.Value.Name)
        Next
    End Sub

    ' Chargement des stations dans la simulation
    Public Sub LoadStations(ByRef Stations As Dictionary(Of Integer, Station), ByRef IncStations As Integer)
        ' On part du principe qu'on a 0 station à lire
        Dim Count As Integer = 0

        ' Si c'est le bon identifiant de section
        If ReadFile.ReadInt16() = STATIONS_SECTION Then
            ' On lit la variable d'incrémentation
            IncStations = ReadFile.ReadInt32()
            ' Et le nombre effectif de stations à lire
            Count = ReadFile.ReadInt32()
        Else
            ' Si on a pas le bon identifiant, on lancer une exception d'entrée/sortie
            Throw New IOException("Identificateur de section STATIONS attendu.")
        End If

        ' Si il y a au moins une station à lire
        If Count > 0 Then
            ' On efface les stations précédentes
            Stations.Clear()

            ' Et on ajout les stations une par une
            For I = 0 To Count - 1
                Stations.Add(ReadFile.ReadInt32(), New Station(ReadFile.ReadInt32(), ReadFile.ReadInt32(), ReadFile.ReadString()))
            Next
        End If
    End Sub

    ' SECTION JUNCTIONS = &HBB
    '   INT RecordCount
    '   ARRAY(JUNCTION) 
    '   <
    '       INT FromStation
    '       INT ToStation
    '   >
    ' END SECTION

    Public Sub WriteJunctions(Junctions As List(Of Junction))
        WriteFile.Write(JUNCTIONS_SECTION)
        WriteFile.Write(Junctions.Count)

        For Each Junction In Junctions
            WriteFile.Write(Junction.FromStation)
            WriteFile.Write(Junction.ToStation)
        Next
    End Sub

    Public Sub LoadJunctions(ByRef Junctions As List(Of Junction), Stations As Dictionary(Of Integer, Station))
        Dim Count As Integer = 0

        If ReadFile.ReadInt16() = JUNCTIONS_SECTION Then
            Count = ReadFile.ReadInt32()
        Else
            Throw New IOException("Identificateur de section JONCTIONS attendu.")
        End If

        If Count > 0 Then
            Junctions.Clear()

            For I = 0 To Count - 1
                Junctions.Add(New Junction(ReadFile.ReadInt32(), ReadFile.ReadInt32(), Stations))
            Next
        End If
    End Sub

    ' SECTION TRAINS = &HCC
    '   INT IncTrains
    '   INT RecordCount
    '   ARRAY(TRAIN) 
    '   <
    '       INT key
    '       INT HeadingTo
    '       INT PrevStation
    '       DOUBLE JunctionPosition
    '       INT WagonCount
    '       INT StopTimer
    '       STRING Name
    '       INT RouteStationsCount
    '       ARRAY(RouteStations) <INT>
    '       INT RouteStopsCount
    '       ARRAY(RouteStops) <INT>
    '   >
    ' END SECTION

    Public Sub WriteTrains(Trains As Dictionary(Of Integer, Train), IncTrains As Integer)
        WriteFile.Write(TRAINS_SECTION)
        WriteFile.Write(IncTrains)
        WriteFile.Write(Trains.Count)

        For Each kvp As KeyValuePair(Of Integer, Train) In Trains
            WriteFile.Write(kvp.Key)
            WriteFile.Write(kvp.Value.HeadingTo)
            WriteFile.Write(kvp.Value.PrevStation)
            WriteFile.Write(kvp.Value.JunctionPosition)
            WriteFile.Write(kvp.Value.WagonCount)
            WriteFile.Write(kvp.Value.StopTimer)
            WriteFile.Write(kvp.Value.Name)

            WriteFile.Write(kvp.Value.Route.Stations.Count)
            For Each Station As Integer In kvp.Value.Route.Stations
                WriteFile.Write(Station)
            Next

            WriteFile.Write(kvp.Value.Route.Stops.Count)
            For Each Stp As Integer In kvp.Value.Route.Stops
                WriteFile.Write(Stp)
            Next
        Next
    End Sub

    Public Sub LoadTrains(ByRef Trains As Dictionary(Of Integer, Train), ByRef IncTrains As Integer)
        Dim Count As Integer = 0

        If ReadFile.ReadInt16() = TRAINS_SECTION Then
            IncTrains = ReadFile.ReadInt32()
            Count = ReadFile.ReadInt32()
        Else
            Throw New IOException("Identificateur de section TRAINS attendu.")
        End If

        If Count > 0 Then
            Trains.Clear()

            For I = 0 To Count - 1
                Trains.Add(ReadFile.ReadInt32(), New Train(ReadFile.ReadInt32(), ReadFile.ReadInt32(), ReadFile.ReadDouble(), _
                                                           ReadFile.ReadInt32(), ReadFile.ReadInt32(), ReadFile.ReadString()))
            Next

            Dim RouteStationsCount As Integer = ReadFile.ReadInt32()

            If RouteStationsCount > 0 Then
                For I = 0 To RouteStationsCount - 1
                    Trains.Last.Value.Route.Stations.Add(ReadFile.ReadInt32())
                Next
            End If

            Dim RouteStopsCount As Integer = ReadFile.ReadInt32()

            If RouteStopsCount > 0 Then
                For I = 0 To RouteStopsCount - 1
                    Trains.Last.Value.Route.Stops.Add(ReadFile.ReadInt32())
                Next
            End If
        End If
    End Sub

    ' SECTION RAILPOINTS = &HDD
    '   INT RecordCount
    '   ARRAY(RAILPOINT) 
    '   <
    '       INT StartStationIndex
    '       INT MiddleStationIndex
    '       INT EndStation1Index
    '       INT EndStation2Index
    '       BOOLEAN ActiveJunction
    '   >
    ' END SECTION

    Public Sub WriteRailPoints(RailPoints As List(Of RailPoint))
        WriteFile.Write(RAILPOINTS_SECTION)
        WriteFile.Write(RailPoints.Count)

        For Each RailPoint In RailPoints
            WriteFile.Write(RailPoint.StartStationIndex)
            WriteFile.Write(RailPoint.MiddleStationIndex)
            WriteFile.Write(RailPoint.EndStation1Index)
            WriteFile.Write(RailPoint.EndStation2Index)
            WriteFile.Write(RailPoint.ActiveJunction)
        Next
    End Sub

    Public Sub LoadRailPoints(ByRef RailPoints As List(Of RailPoint))
        Dim Count As Integer = 0

        If ReadFile.ReadInt16() = RAILPOINTS_SECTION Then
            Count = ReadFile.ReadInt32()
        Else
            Throw New IOException("Identificateur de section AIGUILLAGES attendu.")
        End If

        If Count > 0 Then
            RailPoints.Clear()

            For I = 0 To Count - 1
                RailPoints.Add(New RailPoint(ReadFile.ReadInt32(), ReadFile.ReadInt32(), ReadFile.ReadInt32(), ReadFile.ReadInt32(), ReadFile.ReadBoolean()))
            Next
        End If
    End Sub

    ' Libère la mémoire utilisée par les classes de lecture
    Public Sub Close()
        If Not IsNothing(WriteFile) Then WriteFile.Close()
        If Not IsNothing(ReadFile) Then ReadFile.Close()
    End Sub
End Class
